package cn.thoughtworks.school.pactise.diary.adapters.inbound.rest.resources.practiseDiary;

import cn.thoughtworks.school.pactise.diary.adapters.inbound.rest.auth.annotation.Auth;
import cn.thoughtworks.school.pactise.diary.adapters.inbound.rest.auth.configrations.AuthResolver;
import cn.thoughtworks.school.pactise.diary.application.gateway.user.UserDto;
import cn.thoughtworks.school.pactise.diary.application.gateway.user.UserService;
import cn.thoughtworks.school.pactise.diary.application.usecases.comment.QueryCommentUseCase;
import cn.thoughtworks.school.pactise.diary.application.usecases.practiseDiary.EditExcellentDiaryUseCase;
import cn.thoughtworks.school.pactise.diary.application.usecases.practiseDiary.EditPractiseDiaryUseCase;
import cn.thoughtworks.school.pactise.diary.application.usecases.practiseDiary.QueryExcellentDiaryUseCase;
import cn.thoughtworks.school.pactise.diary.application.usecases.practiseDiary.QueryPractiseDiaryUseCase;
import cn.thoughtworks.school.pactise.diary.domain.context.practiseDiaryContext.practiseDiary.ExcellentDiary;
import cn.thoughtworks.school.pactise.diary.domain.context.practiseDiaryContext.practiseDiary.PractiseDiary;
import cn.thoughtworks.school.pactise.diary.domain.context.practiseDiaryContext.practiseDiary.PractiseDiaryCount;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping(value = "/api/diaries")
public class PractiseDiaryResource {
    private final EditPractiseDiaryUseCase editPractiseDiaryUseCase;
    private final QueryPractiseDiaryUseCase queryPractiseDiaryUseCase;
    private final QueryExcellentDiaryUseCase queryExcellentDiaryUseCase;
    private final EditExcellentDiaryUseCase editExcellentDiaryUseCase;
    private final QueryCommentUseCase queryCommentUseCase;
    private final UserService userService;
    private final PractiseDiaryResourceAssembler practiseDiaryResourceAssembler;

    public PractiseDiaryResource(EditPractiseDiaryUseCase editPractiseDiaryUseCase, QueryPractiseDiaryUseCase queryPractiseDiaryUseCase, QueryExcellentDiaryUseCase queryExcellentDiaryUseCase, EditExcellentDiaryUseCase editExcellentDiaryUseCase, UserService userService, PractiseDiaryResourceAssembler practiseDiaryResourceAssembler, QueryCommentUseCase queryCommentUseCase) {
        this.editPractiseDiaryUseCase = editPractiseDiaryUseCase;
        this.queryPractiseDiaryUseCase = queryPractiseDiaryUseCase;
        this.queryExcellentDiaryUseCase = queryExcellentDiaryUseCase;
        this.editExcellentDiaryUseCase = editExcellentDiaryUseCase;
        this.userService = userService;
        this.practiseDiaryResourceAssembler = practiseDiaryResourceAssembler;
        this.queryCommentUseCase = queryCommentUseCase;
    }

    @RequestMapping(value = "", method = RequestMethod.GET)
    public ResponseEntity<PractiseWithCommentsDto> getByAuthorId(@Auth AuthResolver.User user, @RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "pageSize", defaultValue = "10") Integer size) {
        Sort sort = new Sort(Sort.Direction.DESC, "date");
        Pageable pageable = new PageRequest(page - 1, size, sort);
        List<PractiseDiary> practiseDiaries = queryPractiseDiaryUseCase.findByAuthorId(user.getId(), pageable);

        List<cn.thoughtworks.school.pactise.diary.adapters.inbound.rest.resources.follow.PractiseWithCommentsDto> practiseAndCommentsList = queryCommentUseCase.attachComments(practiseDiaries);
        int total = (queryPractiseDiaryUseCase.findByAuthorIdOrderByDateDesc(user.getId())).size();
        UserDto authorInfo = userService.getDiaryAuthorInfo(user.getId());

        return new ResponseEntity<>(new PractiseWithCommentsDto(total, practiseAndCommentsList, authorInfo), HttpStatus.OK);
    }

    @RequestMapping(value = "", method = RequestMethod.GET, params = {"year", "month"})
    public ResponseEntity<List<PractiseDiaryDto>> getMonthlyDiaryByAuthorId(@Auth AuthResolver.User user,
                                                                            @RequestParam(value = "year") int year,
                                                                            @RequestParam(value = "month") int month) {

        List<PractiseDiary> practiseDiaries = queryPractiseDiaryUseCase.findMonthlyDiariesByAuthorId(user.getId(), year, month);

        List<PractiseDiaryDto> practiseDiaryResources = practiseDiaryResourceAssembler.toResources(practiseDiaries);

        return new ResponseEntity<>(practiseDiaryResources, HttpStatus.OK);
    }


    @RequestMapping(value = "/monthly-count", method = RequestMethod.GET)
    public ResponseEntity<List<PractiseDiaryCount>> getYearSubmitCountByAuthorId(@Auth AuthResolver.User user,
                                                                                 @RequestParam(value = "year") int year) {

        List<PractiseDiaryCount> practiseDiaryCounts = queryPractiseDiaryUseCase.findYearSubmitCountByAuthorId(user.getId(), year);


        return new ResponseEntity<>(practiseDiaryCounts, HttpStatus.OK);
    }


    @RequestMapping(value = "", method = RequestMethod.POST)
    public ResponseEntity<PractiseDiaryCreateDto> createDiary(@Auth AuthResolver.User user, @RequestBody PractiseDiaryRequest practiseDiaryRequest) {

        Date now = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        practiseDiaryRequest.setAuthorId(user.getId());
        practiseDiaryRequest.setCreateTime(simpleDateFormat.format(now));
        PractiseDiary practiseDiary = editPractiseDiaryUseCase.save(practiseDiaryRequest.toDomain());

        String uri = "/api/users/" + user.getId() + "/diaries/" + practiseDiary.getId();

        return new ResponseEntity<>(new PractiseDiaryCreateDto(uri), HttpStatus.CREATED);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public ResponseEntity deleteDiary(@PathVariable long id) {
        if (queryPractiseDiaryUseCase.existsById(id)) {
            ExcellentDiary excellentDiary = queryExcellentDiaryUseCase.findByDiaryId(id);
            if (excellentDiary != null) {
                editExcellentDiaryUseCase.deleteById(excellentDiary.getId());
            }
            editPractiseDiaryUseCase.deleteById(id);
        }
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    //TODO: 这个实现不是特别好，考虑未来改掉它
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public ResponseEntity<?> updateDiary(@PathVariable Long id, @RequestBody PractiseDiaryRequest practiseDiaryRequest) {
        PractiseDiary currentPractiseDiary = queryPractiseDiaryUseCase.findById(id);
        if (currentPractiseDiary == null) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        currentPractiseDiary.setContent(practiseDiaryRequest.getContent());
        currentPractiseDiary.setDate(practiseDiaryRequest.getDate());
        PractiseDiary savedPractiseDiary = editPractiseDiaryUseCase.save(currentPractiseDiary);
        return new ResponseEntity<>(savedPractiseDiary.getId(), HttpStatus.NO_CONTENT);
    }
}
